package controllers

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/sessions"
	pbErrors "github.com/micro/go-micro/v2/errors"
	"github.com/mitchellh/mapstructure"
	"micro-grpc-server/app/common"
	"micro-grpc-server/library/validate"
)

type Controller struct {
	Ctx     iris.Context
	Session *sessions.Session
}

func (c *Controller) UserId() int64 {
	return c.Ctx.Values().GetInt64Default("auth_user_id", -1)
}

func (c *Controller) QueryPage() int {
	return c.Ctx.URLParamIntDefault("page", 1)
}

func (c *Controller) BodyValue(key string) (string, error) {
	return c.BodyValueDefault(key, "")
}

// TODO 封装一下读取 Form Data & Request Payload
func (c *Controller) BodyValueDefault(key string, def string) (s string, err error) {
	return s, err
}

func (c *Controller) ErrorStatus(status int) *Controller {
	c.Ctx.StatusCode(status)
	return c
}

func (c *Controller) JsonErr(errCode int, errMsg string, data interface{}) {
	_, _ = c.Ctx.JSON(common.Response{
		ErrCode: errCode,
		ErrMsg:  errMsg,
		Data:    data,
	}, iris.JSON{
		StreamingJSON: true,
	})
}

func (c *Controller) JsonSuc(data interface{}) {
	c.ErrorStatus(iris.StatusOK).JsonErr(200, "success", data)
}

func (c *Controller) NotFond(data interface{}) {
	c.ErrorStatus(iris.StatusNotFound).JsonErr(404, "not found", data)
}

func (c *Controller) BadRequest(data interface{}) {
	var errMsg = "参数错误"
	if m, ok := data.(string); ok == true {
		errMsg = m
	} else if m, ok := data.(error); ok == true {
		errMsg = m.Error()
	}
	c.ErrorStatus(iris.StatusBadRequest).JsonErr(400, errMsg, data)
}

func (c *Controller) ServerErr(data interface{}) {
	c.ErrorStatus(iris.StatusInternalServerError).JsonErr(500, "service error", data)
}

func (c *Controller) Unauthorized() {
	c.ErrorStatus(iris.StatusUnauthorized).JsonErr(401, "Your request was made with invalid credentials.", "")
}

// 返回一个 bytes 资源
func (c *Controller) WriteImageResource(bytes []byte) {
	var w = c.Ctx.ResponseWriter()
	w.Header().Set("Content-Type", "image/png")
	_, _ = w.Write(bytes)
}

func (c *Controller) JsonSucMeta(data interface{}, extra interface{}) {
	_, _ = c.Ctx.JSON(common.Pagination{
		Response: common.Response{
			ErrCode: 200,
			ErrMsg:  "success",
			Data:    data,
		},
		Extra: extra.(common.Extra),
	}, iris.JSON{
		StreamingJSON: true,
	})
}

// 将参数中对应结构体中的json解析
func (c *Controller) ReadJson(jsonObjectPtr interface{}) (err error) {
	if err = c.Ctx.ReadJSON(jsonObjectPtr); err != nil {
		return err
	}
	if err = validate.CheckStructAuthorized(jsonObjectPtr); err != nil {
		return err
	}
	if err = mapstructure.Decode(c, &jsonObjectPtr); err != nil {
		return errors.New("结构体转换失败. " + err.Error())
	}
	return nil
}

// 将参数中对应结构体中的query解析
func (c *Controller) ReadQuery(jsonObjectPtr interface{}) (err error) {
	if err = c.Ctx.ReadQuery(jsonObjectPtr); err != nil {
		return err
	}
	if err = validate.CheckStructAuthorized(jsonObjectPtr); err != nil {
		return err
	}
	if err = mapstructure.Decode(c, &jsonObjectPtr); err != nil {
		return errors.New("结构体转换失败. " + err.Error())
	}
	return nil
}

func (c *Controller) FriendlyRpcError(err error) string {
	fmt.Println(err)
	var pbErr = &pbErrors.Error{}
	if err := json.Unmarshal([]byte(err.Error()), pbErr); err != nil {
		return "服务返回出现错误"
	}
	return pbErr.Detail
}
